package com.qth.valet.service.impl;

import cn.hutool.json.JSONObject;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.qth.valet.common.config.AliyunSmsConfig;
import com.qth.valet.common.rouyi.StringUtils;
import com.qth.valet.common.theadlocal.UserOrDriverIdHolder;
import com.qth.valet.common.utils.StatusConstants;
import com.qth.valet.common.utils.ToolUtils;
import com.qth.valet.entity.po.Driver;
import com.qth.valet.entity.vo.IncomesVo;
import com.qth.valet.mapper.DriversMapper;
import com.qth.valet.payment.SmsConfig;
import com.qth.valet.service.DriversService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class DriversServiceImpl extends ServiceImpl<DriversMapper, Driver> implements DriversService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private final String PHONE = "phone";

    @Resource
    private SmsConfig smsConfig;

    @Resource
    private IAcsClient iAcsClient;

    @Override
    public boolean updateSts(Integer driverId, Integer status) {
        LambdaUpdateWrapper<Driver> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Driver::getStatus, status)
                .eq(Driver::getId, driverId);
        return this.update(updateWrapper);
    }

    @Override
    public boolean checkVerifyCode(String phone, int verifyCode) {
        String s = stringRedisTemplate.opsForValue().get(PHONE+"_"+phone);
        if (!StringUtils.isBlank(s)) {
            int code = Integer.valueOf(s);
            return code == verifyCode;
        }
        return false;
    }

    @Override
    public void setDriverAddr(Driver driver) {
        if(driver.getLa() != null && driver.getLo() != null){
            JSONObject jsonObject = new JSONObject();
            jsonObject.putOnce(StatusConstants.DRIVER_LA, driver.getLa());
            jsonObject.putOnce(StatusConstants.DRIVER_LO, driver.getLo());

            stringRedisTemplate.opsForHash().put(StatusConstants.DRIVER_LO_LA, driver.getId().toString(), jsonObject.toString());
        }
    }

    @Override
    public void removeDriverAddr(Integer driverId) {
        if(driverId != null){
            stringRedisTemplate.opsForHash().delete(StatusConstants.DRIVER_LO_LA, driverId.toString());
        }
    }

    @Override
    public int createVerifyCode(String phone) {
        int verifyCode = ToolUtils.generateVerifyCode();
        stringRedisTemplate.opsForValue().set(PHONE+"_"+phone, String.valueOf(verifyCode), 5, TimeUnit.MINUTES);

        return verifyCode;
    }

    @Override
    public boolean updateDriverBalancePlus(Integer driverId, Long amount) {
        LambdaUpdateWrapper<Driver> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Driver::getId, driverId);
        updateWrapper.setSql("account_balance = account_balance + " + amount);
        return this.update(updateWrapper);
    }

    @Override
    public boolean updateDriverBalanceMinus(Integer driverId, Long amount) {
        LambdaUpdateWrapper<Driver> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Driver::getId, driverId);
        updateWrapper.setSql("account_balance = account_balance - " + amount);
        return this.update(updateWrapper);
    }

    @Override
    public List<Map<Object, Object>> getAllDriverAddr() {
        // 获取哈希表中所有的键值对
        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(StatusConstants.DRIVER_LO_LA);

        // 遍历键值对
        List<Map<Object, Object>> list = new ArrayList<>();
        for (Map.Entry<Object, Object> entry : entries.entrySet()) {
            Object hashKey = entry.getKey();      // 哈希表中的字段
            Object hashValue = entry.getValue();  // 哈希表中的值
            Map<Object, Object> map = new HashMap<>();
            map.put(hashKey, hashValue);
            list.add(map);
        }
        return list;
    }

    @Override
    public boolean sendMsm(String phoneNumber, int code) {
        try {

            SendSmsRequest request = new SendSmsRequest();
            // 必填:待发送手机号
            request.setPhoneNumbers(phoneNumber);
            // 必填:短信签名-可在短信控制台中找到
            request.setSignName(smsConfig.getSignName());
            // 必填:短信模板-可在短信控制台中找到
            request.setTemplateCode(smsConfig.getTemplateCode());
            // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            request.setTemplateParam("{\"code\":\"" + code + "\"}");

            request.setSysConnectTimeout(5000);

            request.setSysReadTimeout(10000);

            // 发送请求并获取返回
            SendSmsResponse response = iAcsClient.getAcsResponse(request);

            log.info("手机号：{}, message：{}", phoneNumber, response.getMessage());

            return "OK".equals(response.getCode());
        } catch (ClientException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void updateNoticeReadStatus(Integer driverId, boolean status) {
        LambdaUpdateWrapper<Driver> uw = new LambdaUpdateWrapper<Driver>()
                .eq(Driver::getId, driverId)
                .set(Driver::getIsNoticeRead, status);
        this.update(uw);
    }
}
